package com.reason.search.service.impl;

import com.alibaba.fastjson.JSON;
import com.reason.search.pojo.CustomerInfo;
import com.reason.search.service.SearchService;
import com.reason.user.pojo.Customer;
import com.reason.user.pojo.Economics;
import com.reason.user.pojo.Job;
import com.reason.user.pojo.Marriage;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.GetQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zhangHeng
 * @date 2020/7/1 19:02
 */
@Service
public class SearchServiceImpl implements SearchService {
    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    /**
     * 条件查询
     * @param searchMap
     * @return
     */
    @Override
    public Map search(Map<String, String> searchMap) {
        //3.构建布尔查询
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //3.1->根据昵称查找
        String nick = searchMap.get("nick");
        if(StringUtils.isNotBlank(nick)){
            boolQuery.filter(QueryBuilders.matchQuery("nick",nick));
        }

        //3.2->根据性别查找
        String sex = searchMap.get("sex");
        if(StringUtils.isNotBlank(sex)){
            boolQuery.filter(QueryBuilders.termQuery("sex",sex));
        }

        //3.3—>根据年龄查找
        String age = searchMap.get("age");
        if (StringUtils.isNotBlank(age)){
            String[] split = age.split("-");
            boolQuery.filter(QueryBuilders.rangeQuery("age").gte(split[0]));
            if(split.length==2) {
                boolQuery.filter(QueryBuilders.rangeQuery("age").lte(split[1]));
            }
        }

        //3.4->根据地址查找
        String address = searchMap.get("address");
        if(StringUtils.isNotBlank(address)){
            boolQuery.filter(QueryBuilders.matchQuery("address",address));
        }

        //3.5->根据学历查找
        String education = searchMap.get("education");
        if(StringUtils.isNotBlank(education)){
            boolQuery.filter(QueryBuilders.termQuery("education",education));

        }
        //3.6->根据身高查询
        Integer height = Integer.parseInt(searchMap.get("height"));

        String s = String.valueOf(height);
        if(StringUtils.isNotBlank(s)){
            String[] split1 = s.split("-");
            boolQuery.filter(QueryBuilders.rangeQuery("height").gte(split1[0]));
            if (split1.length==2){
                boolQuery.filter(QueryBuilders.rangeQuery("height").lte(split1[1]));
            }
        }
        //婚姻状态
        String marital_status = searchMap.get("marital_status");
        if(StringUtils.isNotBlank(marital_status)){
            boolQuery.filter(QueryBuilders.termQuery("maritalStatus",marital_status));
        }
        //月薪查询
        String salary = searchMap.get("salary");
        if(StringUtils.isNotBlank(salary)){
            boolQuery.filter(QueryBuilders.termQuery("salary",salary));
        }
        //是否有车查询
        String car = searchMap.get("car");
        if(StringUtils.isNotBlank(car)){
            boolQuery.filter(QueryBuilders.termQuery("car",car));
        }
        //是否有房查询
        String house = searchMap.get("house");
        if (StringUtils.isNotBlank(house)){
            boolQuery.filter(QueryBuilders.termQuery("house",height));

        }
        //是否有孩子
        String children = searchMap.get("children");
        if(StringUtils.isNotBlank(children)){
            boolQuery.filter(QueryBuilders.termQuery("children",children));
        }


        // 5.分页 -> 默认查询第1页，每页30条数据（每页最多50条数据）
        int page = 1;
        int size = 30;
        String pageNum = searchMap.get("pageNum");
        String pageSize = searchMap.get("pageSize");
        try {
            page = Integer.parseInt(pageNum);
        } catch (Exception ignored) {
            ignored.printStackTrace();
        }
        try {
            size = Math.min(Integer.parseInt(pageSize), 50);
        } catch (Exception ignored) {
            ignored.printStackTrace();
        }
        PageRequest pageRequest = PageRequest.of(page, size);
        //2.构建查询条件封装对象
        NativeSearchQueryBuilder nativeSearchQueryBuilder=new NativeSearchQueryBuilder()
                .withQuery(boolQuery)
                .withPageable(pageRequest)
                ;

        //1.开启查询
        AggregatedPage<CustomerInfo> resultInfo = elasticsearchRestTemplate.queryForPage(nativeSearchQueryBuilder.build(), CustomerInfo.class);
        if (resultInfo == null) {
            return Collections.emptyMap();
        }
        //封装查询条件
        Map<String, Object> resultMap = new HashMap<>(5);
        resultMap.put("rows", resultInfo.getContent());
        resultMap.put("total", resultInfo.getTotalElements());
        resultMap.put("totalPages", resultInfo.getTotalPages());
        resultMap.put("pageNum", page);
        resultMap.put("pageSize", size);
        return resultMap;
    }

    /**
     * 根据ID查询用户
     * @param cusId
     * @return
     */
    @Override
    public Map<String,Object> searchById(Long cusId) {
        Map<String,Object> map=new HashMap<>();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolQuery.must(QueryBuilders.termQuery("id",cusId));
        String cusIdStr = String.valueOf(cusId);
        GetQuery getQuery=new GetQuery();

        getQuery.setId(cusIdStr);
        CustomerInfo customerInfo = elasticsearchRestTemplate.queryForObject(getQuery, CustomerInfo.class);
        Map totalMap = JSON.parseObject(JSON.toJSONString(customerInfo), Map.class);
        //获取用户经济实力数据
        String economics = customerInfo.getEconomics();
        Map economicsMap = JSON.parseObject(economics, Map.class);
        //获取婚姻观念数据
        String marriage = customerInfo.getMarriage();
        Map marriageMap = JSON.parseObject(marriage, Map.class);
        //获取工作学习数据
        String job = customerInfo.getJob();
        Map jobMap = JSON.parseObject(job, Map.class);
        //获取择偶数据
        String condition = customerInfo.getCondition();
        Map conditionMap = JSON.parseObject(condition, Map.class);
        //获取用户生活数据
        String lifeStyle = customerInfo.getLifeStyle();
        Map lifeStyleMap = JSON.parseObject(lifeStyle, Map.class);

        totalMap.put("economicsData",economicsMap);
        totalMap.put("marriageData",marriageMap);
        totalMap.put("jobData",jobMap);
        totalMap.put("conditionData",conditionMap);
        totalMap.put("lifeStyleData",lifeStyleMap);
        //查询相似用户
        List<CustomerInfo> likeCus = this.findLikeCus(customerInfo.getAge(),customerInfo.getAddress());
        map.put("customerData",totalMap);
        map.put("similarList",likeCus);

        return map;

    }

    /**
     * 根据用户查询相关相似用户
     * @return 相似用户集合
     */
    public List<CustomerInfo> findLikeCus(Integer age,String address){

        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolQuery.must(QueryBuilders.rangeQuery("age").gte(String.valueOf(age-5)));
        boolQuery.must(QueryBuilders.rangeQuery("age").lte(String.valueOf(age+5)));

        boolQuery.must(QueryBuilders.termQuery("address",address));
        NativeSearchQueryBuilder nativeSearchQueryBuilder=new NativeSearchQueryBuilder().withQuery(boolQuery);

        List<CustomerInfo> customerInfos = elasticsearchRestTemplate.queryForList(nativeSearchQueryBuilder.build(), CustomerInfo.class);

        return customerInfos;
    }
}
